package com.nononsenseapps.feeder.ui.common

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.LinearLayout
import timber.log.Timber
import kotlin.math.abs

const val TIMEOUT = 300

class BicontLayout : LinearLayout {
    private lateinit var dividerView: View
    private lateinit var vTopView: View
    private lateinit var vBottomView: View
    private lateinit var vTopParams: LayoutParams
    private lateinit var vBottomParams: LayoutParams
    private var dividerClickableHeight = 0
    private var weightChangedListener:((newTopWeight:Float)->Unit)?=null

    var panelOpenHideChangedListener:PanelOpenHideChangedListener?=null
       set(value) {
           field=value
           if(value!=null)
               maxPanelModelAble=true
       }

    var maxPanelModelAble=false

    private var maxPanelModel=false
    private var leftPanelMaxModel=false

    constructor(context: Context): super(context)
    constructor(context: Context, attrs: AttributeSet?): super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr)

    fun initLayout(vTopViewID: Int, deviderID: Int, vBottomID: Int,vTopWeight: Float?=null,weightChangedListener:((newTopWeight:Float)->Unit)?=null) {
        this.weightChangedListener=weightChangedListener
        vTopView = findViewById(vTopViewID)
        vTopParams = vTopView.layoutParams as LayoutParams
        dividerView = findViewById(deviderID)
        val dividerParams = dividerView.layoutParams as LayoutParams
        dividerClickableHeight = if (this.orientation == HORIZONTAL) dividerParams.width else dividerParams.height
        vBottomView = findViewById(vBottomID)
        vBottomParams = vBottomView.layoutParams as LayoutParams
        val totalWeight = vTopParams.weight + vBottomParams.weight
        if(vTopWeight!=null){
            vTopParams.weight =vTopWeight
        }else {
            vTopParams.weight = vTopParams.weight / totalWeight
        }
        vBottomParams.weight = 1.0f - vTopParams.weight
        vTopView.layoutParams = vTopParams
        vBottomView.layoutParams = vBottomParams
    }

    private var startTouch = 0f
    private var startWeight = 0f
    private var isDragging = false
    private val dividerLocation = IntArray(2)

    private var clickCount = 0

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        //Timber.d("onInterceptTouchEvent downTime:${ev.eventTime-ev.downTime} \t ")
        return if (onTouchEvent(ev)) true else super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(me: MotionEvent): Boolean {
        when (me.action) {
            MotionEvent.ACTION_DOWN -> {
                if(!maxPanelModel) {
                    dividerView.getLocationOnScreen(dividerLocation)
                    if (this.orientation == VERTICAL) {
                        startTouch = me.rawY
                        isDragging = abs(dividerLocation[1] - startTouch) < dividerClickableHeight / 2
                    } else {
                        startTouch = me.rawX
                        isDragging = abs(dividerLocation[0] - startTouch) < dividerClickableHeight / 2
                    }
                    if (isDragging)
                        startWeight = vTopParams.weight
                }
            }
            MotionEvent.ACTION_MOVE -> {
                if (isDragging) {
                    val delta =if (this.orientation == VERTICAL) { me.rawY - startTouch} else  startTouch-me.rawX
                    val deltaProg =if (this.orientation == VERTICAL) {delta / this@BicontLayout.height } else delta / this@BicontLayout.width
                    var newProg = startWeight + deltaProg
                    if (newProg < 0.1f) newProg = 0.1f
                    if (newProg > 0.9f) newProg = 0.9f
                    vTopParams.weight = newProg
                    vTopView.layoutParams = vTopParams
                    vBottomParams.weight = 1f - newProg
                    vBottomView.layoutParams = vBottomParams
                }
            }
            MotionEvent.ACTION_UP -> {
                Timber.d("onTouchEvent ACTION_UP downTime:${me.downTime} eventTime:${me.eventTime}\t countTime:${me.eventTime-me.downTime} \t ")
                if(isDragging)
                    weightChangedListener?.invoke(vTopParams.weight)
                else
                    if(maxPanelModelAble) {
                        clickCount++
                        handler?.postDelayed({
                            Timber.d("handler run clickCount:$clickCount")
                            if (clickCount >= 2) {
                                if (maxPanelModel) {
                                    onDoubleClick(leftPanelMaxModel)
                                } else {
                                    if (isTouchPointInView(vTopView, me.rawX.toInt(), me.rawY.toInt()))
                                        onDoubleClick(true)
                                    else if (isTouchPointInView(vBottomView, me.rawX.toInt(), me.rawY.toInt()))
                                        onDoubleClick(false)
                                }
                            }
                            handler.removeCallbacksAndMessages(null)
                            clickCount = 0
                        }, TIMEOUT.toLong())
                    }
                isDragging = false
            }
        }
        return if (isDragging) true else super.onTouchEvent(me)
    }

    fun isTouchPointInView(view: View, x: Int, y: Int): Boolean {
        val location = IntArray(2)
        view.getLocationOnScreen(location)
        val left = location[0]
        val top = location[1]
        val right = left + view.measuredWidth
        val bottom = top + view.measuredHeight

        return y in top..bottom && x >= left && x <= right
    }
    
   fun onDoubleClick(isLeft:Boolean){
       Timber.d("onDoubleClick isLeft:$isLeft \t  isMaxPanelModel:$maxPanelModel\t isLeftPanelMaxModel:$leftPanelMaxModel")
       if(maxPanelModel){
           if(leftPanelMaxModel){
               vBottomView.visibility=View.VISIBLE
           }else{
               vTopView.visibility=View.VISIBLE
           }
           maxPanelModel=false
           leftPanelMaxModel=false
           panelOpenHideChangedListener?.resetToBefore()
       }else{
           maxPanelModel=true
           if(isLeft){
               vBottomView.visibility=View.GONE
               leftPanelMaxModel=true
               panelOpenHideChangedListener?.leftPanelMaxed()
           }else{
               vTopView.visibility=View.GONE
               leftPanelMaxModel=false
               panelOpenHideChangedListener?.rightPanelMaxed()
           }
       }
   }

   fun isMaxPanelModel()=maxPanelModel

   fun isLeftPanelMaxModel()=leftPanelMaxModel

   fun isRightPanelMaxModel()= maxPanelModel&&!leftPanelMaxModel

   fun resetToBefore(){
       if(maxPanelModel) {
           if (leftPanelMaxModel) {
               vBottomView.visibility = View.VISIBLE
           } else {
               vTopView.visibility = View.VISIBLE
           }
           maxPanelModel = false
           leftPanelMaxModel = false
           panelOpenHideChangedListener?.resetToBefore()
       }
   }

    fun setRightViewMargins(left:Int=0, top:Int=0, right:Int=0, bottom:Int=0){
        vBottomParams.setMargins(left,top,right,bottom)
        vBottomView.layoutParams = vBottomParams
    }
}

interface PanelOpenHideChangedListener{
    fun leftPanelMaxed()
    fun rightPanelMaxed()
    fun resetToBefore()
}